package com.mask.im.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mask.im.business.common.constant.CommonConstant;
import com.mask.im.business.model.entity.ResourceRole;
import com.mask.im.business.model.entity.SysRoleEntity;
import com.mask.im.business.model.entity.SysRoleMenuEntity;
import com.mask.im.business.model.entity.UserRole;
import com.mask.im.business.common.exception.BusinessException;
import com.mask.im.business.mapper.SysRoleMapper;
import com.mask.im.business.mapper.UserRoleMapper;
import com.mask.im.business.model.dto.RoleDTO;
import com.mask.im.business.model.dto.UserRoleDTO;
import com.mask.im.business.model.vo.ConditionVO;
import com.mask.im.business.common.model.PageResult;
import com.mask.im.business.model.vo.RoleVO;
import com.mask.im.business.service.ResourceRoleService;
import com.mask.im.business.service.SysRoleMenuService;
import com.mask.im.business.service.SysRoleService;
import com.mask.im.business.common.util.BeanCopy;
import com.mask.im.business.common.util.PageUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


/**
 * 角色管理
 *
 * @author jian
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRoleEntity> implements SysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private ResourceRoleService roleResourceService;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;


    @Override
    public List<UserRoleDTO> listUserRoles() {
        List<SysRoleEntity> sysRoleEntityList = sysRoleMapper.selectList(new LambdaQueryWrapper<SysRoleEntity>()
                .select(SysRoleEntity::getId, SysRoleEntity::getRoleName));
        return BeanCopy.listCopy(sysRoleEntityList, UserRoleDTO.class);
    }

    @SneakyThrows
    @Override
    public PageResult<RoleDTO> listRoles(ConditionVO conditionVO) {
        LambdaQueryWrapper<SysRoleEntity> queryWrapper = new LambdaQueryWrapper<SysRoleEntity>()
                .like(StringUtils.isNotBlank(conditionVO.getKeywords()), SysRoleEntity::getRoleName, conditionVO.getKeywords());
        CompletableFuture<Integer> asyncCount = CompletableFuture.supplyAsync(() -> sysRoleMapper.selectCount(queryWrapper));
        List<RoleDTO> roleDTOs = baseMapper.listRoles(PageUtil.getCurrentPage(), PageUtil.getSize(), conditionVO);
        return PageResult.<RoleDTO>builder().data(roleDTOs).total(asyncCount.get()).build();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdateRole(RoleVO roleVO) {
        SysRoleEntity sysRoleEntityCheck = sysRoleMapper.selectOne(new LambdaQueryWrapper<SysRoleEntity>()
                .select(SysRoleEntity::getId)
                .eq(SysRoleEntity::getRoleName, roleVO.getRoleName()));
        if (Objects.nonNull(sysRoleEntityCheck) && !(sysRoleEntityCheck.getId().equals(roleVO.getId()))) {
            throw new BusinessException("该角色存在");
        }
        SysRoleEntity sysRoleEntity = SysRoleEntity.builder()
                .id(roleVO.getId())
                .roleName(roleVO.getRoleName())
                .isDisable(CommonConstant.FALSE)
                .build();
        this.saveOrUpdate(sysRoleEntity);
        if (Objects.nonNull(roleVO.getResourceIds())) {
            if (Objects.nonNull(roleVO.getId())) {
                roleResourceService.remove(new LambdaQueryWrapper<ResourceRole>()
                        .eq(ResourceRole::getRoleId, roleVO.getId()));
            }
            List<ResourceRole> roleResourceList = roleVO.getResourceIds().stream()
                    .map(resourceId -> ResourceRole.builder()
                            .roleId(sysRoleEntity.getId())
                            .resourceId(resourceId)
                            .build())
                    .collect(Collectors.toList());
            roleResourceService.saveBatch(roleResourceList);
//            filterInvocationSecurityMetadataSource.clearDataSource();
        }
        if (Objects.nonNull(roleVO.getMenuIds())) {
            if (Objects.nonNull(roleVO.getId())) {
                sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenuEntity>().eq(SysRoleMenuEntity::getRoleId, roleVO.getId()));
            }
            List<SysRoleMenuEntity> roleMenuList = roleVO.getMenuIds().stream()
                    .map(menuId -> SysRoleMenuEntity.builder()
                            .roleId(sysRoleEntity.getId())
                            .menuId(menuId)
                            .build())
                    .collect(Collectors.toList());
            sysRoleMenuService.saveBatch(roleMenuList);
        }
    }

    @Override
    public void deleteRoles(List<Integer> roleIdList) {
        Integer count = userRoleMapper.selectCount(new LambdaQueryWrapper<UserRole>()
                .in(UserRole::getRoleId, roleIdList));
        if (count > 0) {
            throw new BusinessException("该角色下存在用户");
        }
        sysRoleMapper.deleteBatchIds(roleIdList);
    }
}

